// UIImageView+AFNetworking.m
//
// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#import "UIImageView+AFNetworking.h"
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonDigest.h>
#include <fcntl.h>
#include <unistd.h>
#import <objc/runtime.h>

#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)

#import "AFHTTPRequestOperation.h"

@interface AFImageCache : NSCache <AFImageCache>
@end

#pragma mark -

@interface UIImageView (_AFNetworking)
@property (readwrite, nonatomic, strong, setter = af_setImageRequestOperation:) AFHTTPRequestOperation *af_imageRequestOperation;
@end

@implementation UIImageView (_AFNetworking)

+ (NSOperationQueue *)af_sharedImageRequestOperationQueue {
    static NSOperationQueue *_af_sharedImageRequestOperationQueue = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _af_sharedImageRequestOperationQueue = [[NSOperationQueue alloc] init];
        _af_sharedImageRequestOperationQueue.maxConcurrentOperationCount = NSOperationQueueDefaultMaxConcurrentOperationCount;
    });

    return _af_sharedImageRequestOperationQueue;
}

- (AFHTTPRequestOperation *)af_imageRequestOperation {
    return (AFHTTPRequestOperation *)objc_getAssociatedObject(self, @selector(af_imageRequestOperation));
}

- (void)af_setImageRequestOperation:(AFHTTPRequestOperation *)imageRequestOperation {
    objc_setAssociatedObject(self, @selector(af_imageRequestOperation), imageRequestOperation, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end

#pragma mark -

@implementation UIImageView (AFNetworking)
@dynamic imageResponseSerializer;

+ (id <AFImageCache>)sharedImageCache {
    static AFImageCache *_af_defaultImageCache = nil;
    static dispatch_once_t oncePredicate;
    dispatch_once(&oncePredicate, ^{
        _af_defaultImageCache = [[AFImageCache alloc] init];

        [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidReceiveMemoryWarningNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * __unused notification) {
            [_af_defaultImageCache removeAllObjects];
        }];
    });

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
    return objc_getAssociatedObject(self, @selector(sharedImageCache)) ?: _af_defaultImageCache;
#pragma clang diagnostic pop
}

+ (void)setSharedImageCache:(id<AFImageCache>)imageCache {
    objc_setAssociatedObject(self, @selector(sharedImageCache), imageCache, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (id <AFURLResponseSerialization>)imageResponseSerializer {
    static id <AFURLResponseSerialization> _af_defaultImageResponseSerializer = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _af_defaultImageResponseSerializer = [AFImageResponseSerializer serializer];
    });

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
    return objc_getAssociatedObject(self, @selector(imageResponseSerializer)) ?: _af_defaultImageResponseSerializer;
#pragma clang diagnostic pop
}

- (void)setImageResponseSerializer:(id <AFURLResponseSerialization>)serializer {
    objc_setAssociatedObject(self, @selector(imageResponseSerializer), serializer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

#pragma mark -

- (void)setImageWithURL:(NSURL *)url {
    [self setImageWithURL:url placeholderImage:nil];
}

- (void)setImageWithURL:(NSURL *)url
       placeholderImage:(UIImage *)placeholderImage
{
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request addValue:@"image/*" forHTTPHeaderField:@"Accept"];

    [self setImageWithURLRequest:request placeholderImage:placeholderImage success:nil failure:nil];
}


//- (void)setImageWithURLRequest:(NSURLRequest *)urlRequest
//              placeholderImage:(UIImage *)placeholderImage
//                       success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success
//                       failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure
//{
//    [self cancelImageRequestOperation];
//    
//    if ([urlRequest cachePolicy] == NSURLRequestReloadIgnoringCacheData || [urlRequest cachePolicy] == NSURLRequestReloadIgnoringLocalAndRemoteCacheData) {
//        
//    }else{
//        NSString *pictureBasePath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/Pictures"];
//        BOOL isDirectory = YES;
//        BOOL folderExists = [[NSFileManager defaultManager] fileExistsAtPath:pictureBasePath isDirectory:&isDirectory] && isDirectory;
//        if (!folderExists){
//            NSError *error = nil;
//            [[NSFileManager defaultManager] createDirectoryAtPath:pictureBasePath withIntermediateDirectories:YES attributes:nil error:&error];
//            if (error) {
//                DLog(@"Picutures文件夹创建失败");
//            }else{
//                DLog(@"Picutures文件夹创建成功");
//            }
//        }
//        
//        if ([[NSFileManager defaultManager] fileExistsAtPath:pictureBasePath]) {
//            if (urlRequest.URL) {
//                NSString *pictureName = [self md5StringForString:urlRequest.URL.absoluteString];
//                NSString *picturePath = [NSString pathWithComponents:[NSArray arrayWithObjects:pictureBasePath, pictureName, nil]];
//                if ([[NSFileManager defaultManager] fileExistsAtPath:picturePath]) {
//                    UIImage *cachedImage = [UIImage imageWithContentsOfFile:picturePath];
//                    self.image = cachedImage;
//                    self.af_imageRequestOperation = nil;
//                    if (success) {
//                        [self setImage:cachedImage];
//                        success(nil, nil, cachedImage);
//                    }
//                    return;
//                }
//                
//            }
//        }
//    }
//    
//    
//    UIImage *cachedImage = [[[self class] sharedImageCache] cachedImageForRequest:urlRequest];
//    if (cachedImage) {
//        
//        self.image = cachedImage;
//        self.af_imageRequestOperation = nil;
//        
//        if (success) {
//            success(nil, nil, cachedImage);
//        }
//    } else {
//        NSString *urlString = [[urlRequest URL] absoluteString];
//        NSData *data = [self loadImageData:[self pathInCacheDirectory:@"WendaleCache"] imageName:[urlString md5String]];
//        if (data) {
//            self.image = [UIImage imageWithData:data];
//            self.af_imageRequestOperation = nil;
//            
//            if (success) {
//                success(nil, nil, self.image);
//            }
//            return;
//        }
//
//        self.image = placeholderImage;
//        
//        AFHTTPRequestOperation *requestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:urlRequest];
//        [requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
//            if ([[urlRequest URL] isEqual:[[self.af_imageRequestOperation request] URL]]) {
//                if (success) {
//                    success(operation.request, operation.response, responseObject);
//                }else if (responseObject) {
//                    self.image = responseObject;
//                }
//                //图片本地缓存
//                if ([self createDirInCache:@"WendaleCache"]) {
//                    NSString *imageType = @"png";
//                    //从url中获取图片类型
//                    　　NSMutableArray *arr = (NSMutableArray *)[urlString componentsSeparatedByString:@"."];
//                    if (arr) {
//                        imageType = [arr objectAtIndex:arr.count-1];
//                    }
//                    [self saveImageToCacheDir:[self pathInCacheDirectory:@"WendaleCache"] image: responseObject imageName:[urlString md5String] imageType:imageType];
//                }
//
//                
//                
//                self.af_imageRequestOperation = nil;
//            }
//            
//            [[[self class] sharedImageCache] cacheImage:responseObject forRequest:urlRequest];
//            
//        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//            if ([[urlRequest URL] isEqual:[[self.af_imageRequestOperation request] URL]]) {
//                if (failure) {
//                    failure(operation.request, operation.response, error);
//                }
//                
//                self.af_imageRequestOperation = nil;
//            }
//        }];
//        
//        self.af_imageRequestOperation = requestOperation;
//        
//        [[[self class] af_sharedImageRequestOperationQueue] addOperation:self.af_imageRequestOperation];
//    }
//}



- (void)setImageWithURLRequest:(NSURLRequest *)urlRequest
              placeholderImage:(UIImage *)placeholderImage
                       success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success
                       failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure
{
    [self cancelImageRequestOperation];
    
    if ([urlRequest cachePolicy] == NSURLRequestReloadIgnoringCacheData || [urlRequest cachePolicy] == NSURLRequestReloadIgnoringLocalAndRemoteCacheData) {
        
    }else{
        NSString *pictureBasePath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/Pictures"];
        BOOL isDirectory = YES;
        BOOL folderExists = [[NSFileManager defaultManager] fileExistsAtPath:pictureBasePath isDirectory:&isDirectory] && isDirectory;
        if (!folderExists){
            NSError *error = nil;
            [[NSFileManager defaultManager] createDirectoryAtPath:pictureBasePath withIntermediateDirectories:YES attributes:nil error:&error];
            if (error) {
                NSLog(@"Picutures文件夹创建失败");
            }else{
                
                NSLog(@"pictureBasePath=========%@",pictureBasePath);
                [self addSkipBackupAttributeToItemAtURL:[NSURL fileURLWithPath:pictureBasePath]];
                NSLog(@"Picutures文件夹创建成功");
            }
        }
        
        if ([[NSFileManager defaultManager] fileExistsAtPath:pictureBasePath]) {
            if (urlRequest.URL) {
                NSString *pictureName = [self md5StringForString:urlRequest.URL.absoluteString];
                NSString *picturePath = [NSString pathWithComponents:[NSArray arrayWithObjects:pictureBasePath, pictureName, nil]];
                if ([[NSFileManager defaultManager] fileExistsAtPath:picturePath]) {
                    UIImage *cachedImage = [UIImage imageWithContentsOfFile:picturePath];
//                    UIImage *cachedImage = [UIImage imageNamed:picturePath];
                    
//                    self.image = cachedImage;
                    self.af_imageRequestOperation = nil;
                    if (success) {
                        [self setImage:cachedImage];
                        success(nil, nil, cachedImage);
                    }
                    return;
                }
                
            }
        }
    }
    
    
    UIImage *cachedImage = [[[self class] sharedImageCache] cachedImageForRequest:urlRequest];
    if (cachedImage) {
        if (success) {
            success(nil, nil, cachedImage);
        } else {
            self.image = cachedImage;
        }
        
        self.af_imageRequestOperation = nil;
    } else {
        if (placeholderImage) {
            self.image = placeholderImage;
        }
        
        __weak __typeof(self)weakSelf = self;
        self.af_imageRequestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:urlRequest];
        self.af_imageRequestOperation.responseSerializer = self.imageResponseSerializer;
        [self.af_imageRequestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
            __strong __typeof(weakSelf)strongSelf = weakSelf;
            if ([[urlRequest URL] isEqual:[strongSelf.af_imageRequestOperation.request URL]]) {
                
                NSString *pictureBasePath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/Pictures"];
                BOOL isDirectory = YES;
                BOOL folderExists = [[NSFileManager defaultManager] fileExistsAtPath:pictureBasePath isDirectory:&isDirectory] && isDirectory;
                if (!folderExists){
                    NSError *error = nil;
                    [[NSFileManager defaultManager] createDirectoryAtPath:pictureBasePath withIntermediateDirectories:YES attributes:nil error:&error];
                    if (error) {
                        NSLog(@"Picutures文件夹创建失败");
                    }else{
                        [self addSkipBackupAttributeToItemAtURL:[NSURL fileURLWithPath:pictureBasePath]];
                        NSLog(@"Picutures文件夹创建成功");
                    }
                }
                
                if ([[NSFileManager defaultManager] fileExistsAtPath:pictureBasePath]) {
                    NSString *pictureName = [self md5StringForString:urlRequest.URL.absoluteString];
                    NSString *picturePath = [NSString pathWithComponents:[NSArray arrayWithObjects:pictureBasePath, pictureName, nil]];
                    if ([urlRequest.URL.absoluteString rangeOfString:@"png"].location != NSNotFound) {
                        [UIImagePNGRepresentation(responseObject) writeToFile:picturePath atomically:YES];
                    }else{
                       [UIImageJPEGRepresentation(responseObject, 0.8) writeToFile:picturePath atomically:YES];
                    }
                    
//                    [[NSFileManager defaultManager] createFileAtPath:picturePath contents:imageData attributes:nil]
                }
                
                if (success) {
                    success(urlRequest, operation.response, responseObject);
                } else if (responseObject) {
                    strongSelf.image = responseObject;
                }
                
                if (operation == strongSelf.af_imageRequestOperation){
                    strongSelf.af_imageRequestOperation = nil;
                }
            }
            
            [[[strongSelf class] sharedImageCache] cacheImage:responseObject forRequest:urlRequest];
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            __strong __typeof(weakSelf)strongSelf = weakSelf;
            if ([[urlRequest URL] isEqual:[strongSelf.af_imageRequestOperation.request URL]]) {
                if (failure) {
                    failure(urlRequest, operation.response, error);
                }
                
                if (operation == strongSelf.af_imageRequestOperation){
                    strongSelf.af_imageRequestOperation = nil;
                }
            }
        }];
        
        [[[self class] af_sharedImageRequestOperationQueue] addOperation:self.af_imageRequestOperation];
    }
}

- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL {
    assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]);
    
    NSError *error = nil;
    BOOL success = [URL setResourceValue: [NSNumber numberWithBool: YES]
                                  forKey: NSURLIsExcludedFromBackupKey error: &error];
    if(!success){
        NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent], error);
    }
    return success;
}

//- (void)setImageWithURLRequest:(NSURLRequest *)urlRequest
//              placeholderImage:(UIImage *)placeholderImage
//                       success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success
//                       failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure
//{
//    [self cancelImageRequestOperation];
//    
//    UIImage *cachedImage = [[[self class] sharedImageCache] cachedImageForRequest:urlRequest];
//    if (cachedImage) {
//        if (success) {
//            success(nil, nil, cachedImage);
//        } else {
//            self.image = cachedImage;
//        }
//        
//        self.af_imageRequestOperation = nil;
//    } else {
//    
//        NSString *urlString = [[urlRequest URL] absoluteString];
//        NSData *data = [self loadImageData:[self pathInCacheDirectory:@"WendaleCache"] imageName:[urlString md5String]];
//        
//        if (data) {
//            self.image = [UIImage imageWithData:data];
//            self.af_imageRequestOperation = nil;
//            
//            if (success) {
//                success(nil, nil, self.image);
//            }
//            return;
//        }
//        
//        if (placeholderImage) {
//            self.image = placeholderImage;
//        }
//
//        __weak __typeof(self)weakSelf = self;
//        self.af_imageRequestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:urlRequest];
//        self.af_imageRequestOperation.responseSerializer = self.imageResponseSerializer;
//        [self.af_imageRequestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
//            __strong __typeof(weakSelf)strongSelf = weakSelf;
//            if ([[urlRequest URL] isEqual:[strongSelf.af_imageRequestOperation.request URL]]) {
//                if (success) {
//                    success(urlRequest, operation.response, responseObject);
//                } else if (responseObject) {
//                    strongSelf.image = responseObject;
//                }
//                
//                //图片本地缓存
//                if ([self createDirInCache:@"WendaleCache"]) {
//                    NSString *imageType = @"png";
//                    //从url中获取图片类型
//                    　　NSMutableArray *arr = (NSMutableArray *)[urlString componentsSeparatedByString:@"."];
//                    if (arr) {
//                        imageType = [arr objectAtIndex:arr.count-1];
//                    }
//                    [self saveImageToCacheDir:[self pathInCacheDirectory:@"WendaleCache"] image: responseObject imageName:[urlString md5String] imageType:imageType];
//                }
//
//                
//                if (operation == strongSelf.af_imageRequestOperation){
//                    strongSelf.af_imageRequestOperation = nil;
//                }
//            }
//            
//            [[[strongSelf class] sharedImageCache] cacheImage:responseObject forRequest:urlRequest];
//        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//            __strong __typeof(weakSelf)strongSelf = weakSelf;
//            if ([[urlRequest URL] isEqual:[strongSelf.af_imageRequestOperation.request URL]]) {
//                if (failure) {
//                    failure(urlRequest, operation.response, error);
//                }
//                
//                if (operation == strongSelf.af_imageRequestOperation){
//                    strongSelf.af_imageRequestOperation = nil;
//                }
//            }
//        }];
//        
//        [[[self class] af_sharedImageRequestOperationQueue] addOperation:self.af_imageRequestOperation];
//    }
//}

- (NSString *)md5StringForString:(NSString *)string {
    const char *str = [string UTF8String];
    unsigned char r[CC_MD5_DIGEST_LENGTH];
    CC_MD5(str, (int)strlen(str), r);
    return [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
            r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10], r[11], r[12], r[13], r[14], r[15]];
}

-(NSString* )pathInCacheDirectory:(NSString *)fileName
{
    NSArray *cachePaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *cachePath = [cachePaths objectAtIndex:0];
    return [cachePath stringByAppendingPathComponent:fileName];
}
//创建缓存文件夹
-(BOOL) createDirInCache:(NSString *)dirName
{
    NSString *imageDir = [self pathInCacheDirectory:dirName];
    BOOL isDir = YES;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL existed = [fileManager fileExistsAtPath:imageDir isDirectory:&isDir];
    BOOL isCreated = NO;
    if ( !(isDir == YES && existed == YES) )
    {
        isCreated = [fileManager createDirectoryAtPath:imageDir withIntermediateDirectories:YES attributes:nil error:nil];
    }
    if (existed) {
        isCreated = YES;
    }
    return isCreated;
}

// 删除图片缓存
- (BOOL) deleteDirInCache:(NSString *)dirName
{
    NSString *imageDir = [self pathInCacheDirectory:dirName];
    BOOL isDir = NO;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL existed = [fileManager fileExistsAtPath:imageDir isDirectory:&isDir];
    bool isDeleted = false;
    if ( isDir == YES && existed == YES )
    {
        isDeleted = [fileManager removeItemAtPath:imageDir error:nil];
    }
    
    return isDeleted;
}

// 图片本地缓存
- (BOOL) saveImageToCacheDir:(NSString *)directoryPath  image:(UIImage *)image imageName:(NSString *)imageName imageType:(NSString *)imageType
{
    BOOL isDir = NO;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL existed = [fileManager fileExistsAtPath:directoryPath isDirectory:&isDir];
    bool isSaved = false;
    if ( isDir == YES && existed == YES )
    {
        if ([[imageType lowercaseString] isEqualToString:@"png"])
        {
            isSaved = [UIImagePNGRepresentation(image) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"png"]] options:NSAtomicWrite error:nil];
        }
        else if ([[imageType lowercaseString] isEqualToString:@"jpg"] || [[imageType lowercaseString] isEqualToString:@"jpeg"])
        {
            isSaved = [UIImageJPEGRepresentation(image, 1.0) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"jpg"]] options:NSAtomicWrite error:nil];
        }
        else
        {
            NSLog(@"Image Save Failed\nExtension: (%@) is not recognized, use (PNG/JPG)", imageType);
        }
    }
    return isSaved;
}
// 获取缓存图片
-(NSData*) loadImageData:(NSString *)directoryPath imageName:( NSString *)imageName
{
    BOOL isDir = NO;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL dirExisted = [fileManager fileExistsAtPath:directoryPath isDirectory:&isDir];
    if ( isDir == YES && dirExisted == YES )
    {
        NSString *imagePath = [directoryPath stringByAppendingString : [NSString stringWithFormat:@"/%@.png",imageName]];
        BOOL fileExisted = [fileManager fileExistsAtPath:imagePath];
        if (!fileExisted) {
            return NULL;
        }
        NSData *imageData = [NSData dataWithContentsOfFile : imagePath];
        return imageData;
    }
    else
    {
        return NULL;
    }
}

- (void)cancelImageRequestOperation {
    [self.af_imageRequestOperation cancel];
    self.af_imageRequestOperation = nil;
}

@end

#pragma mark -

static inline NSString * AFImageCacheKeyFromURLRequest(NSURLRequest *request) {
    return [[request URL] absoluteString];
}

@implementation AFImageCache

- (UIImage *)cachedImageForRequest:(NSURLRequest *)request {
    switch ([request cachePolicy]) {
        case NSURLRequestReloadIgnoringCacheData:
        case NSURLRequestReloadIgnoringLocalAndRemoteCacheData:
            return nil;
        default:
            break;
    }

	return [self objectForKey:AFImageCacheKeyFromURLRequest(request)];
}

- (void)cacheImage:(UIImage *)image
        forRequest:(NSURLRequest *)request
{
    if (image && request) {
        [self setObject:image forKey:AFImageCacheKeyFromURLRequest(request)];
    }
}

@end

#endif
